package com.hxx.widget.switch

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import androidx.core.content.res.ResourcesCompat
import com.hxx.widget.R
import com.hxx.widget.getMode
import com.hxx.widget.getSize

class SwitchButton @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr), View.OnClickListener {
    /**
     * 当前状态
     */
    private var stateChecked = false
        set(value) {
            onCheckStateChangedListener(value)
            field = value
        }
    var onCheckStateChangedListener: (Boolean) -> Unit = {}
    private var colorBackground =
        ResourcesCompat.getColor(resources, R.color.widget_grey_300, context.theme)
    private var colorStateSelected =
        ResourcesCompat.getColor(resources, R.color.widget_switch_selected, context.theme)
    private var colorCircle =
        ResourcesCompat.getColor(resources, R.color.widget_switch_circle, context.theme)

    private val sizeCircleRadius =
        resources.getDimensionPixelOffset(R.dimen.widget_switch_button_radius)
    private val sizeCircleStrokeWidth =
        resources.getDimensionPixelOffset(R.dimen.widget_switch_button_stroke_width)

    private var cacheRectF = RectF()
    private var innerRectF = RectF()

    private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)

    init {
        setOnClickListener(this)
    }

    private var circleSeletedStateX = 0f
    private var circleUnSeletedStateX = 0f
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        circleCenterY = paddingTop + (h - paddingBottom - paddingTop) / 2f

        cacheRectF.set(
            paddingStart.toFloat(),
            circleCenterY - sizeCircleStrokeWidth - sizeCircleRadius,
            (w - paddingEnd).toFloat(),
            circleCenterY + sizeCircleStrokeWidth + sizeCircleRadius
        )


        circleSeletedStateX = w - paddingEnd - (sizeCircleRadius + sizeCircleStrokeWidth) * 1f
        circleUnSeletedStateX = paddingStart + (sizeCircleRadius + sizeCircleStrokeWidth) * 1f
        currentCircleX = if (stateChecked) circleSeletedStateX else circleUnSeletedStateX

        val top = cacheRectF.top
        val bottom = cacheRectF.bottom
        val left = cacheRectF.left
        var right = cacheRectF.left
        if (stateChecked) {
            right = cacheRectF.right
        }
        innerRectF.set(left, top, right, bottom)
    }


    fun setCheckedState(isSelected: Boolean) {
        this.stateChecked = isSelected
        startStateChangedAnim()
    }

    private var currentCircleX = 0f
    private var anim: ValueAnimator? = null
    private fun startStateChangedAnim() {
        anim?.cancel()
        val directions = if (stateChecked) floatArrayOf(0f, 1f) else floatArrayOf(1f, 0f)
        anim = ValueAnimator.ofFloat(directions[0], directions[1]).apply {
            addUpdateListener { value ->
                val currentAnimProgress = value.animatedValue as Float
                currentCircleX =
                    circleUnSeletedStateX + (circleSeletedStateX - circleUnSeletedStateX) * currentAnimProgress
                innerRectF.right =
                    (width - paddingStart - paddingEnd) * currentAnimProgress + paddingStart
                invalidate()
            }
            duration = 150
            start()
        }
    }

    private var circleCenterY = 0f
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val circleHeight = (sizeCircleRadius + sizeCircleStrokeWidth) * 2
        val circleWidth = circleHeight * 1.85

        val widthNeed = circleWidth + paddingStart + paddingEnd
        val heightNeed = circleHeight + paddingTop + paddingBottom

        var targetHeight = heightNeed
        if (heightMeasureSpec.getMode() == MeasureSpec.EXACTLY) {
            targetHeight = heightMeasureSpec.getSize()
        }
        setMeasuredDimension(widthNeed.toInt(), targetHeight)
    }

    private val roundRadius = sizeCircleRadius + sizeCircleStrokeWidth * 1f
    private val xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val count = canvas.saveLayer(null, null)
        paint.color = colorBackground
        canvas.drawRoundRect(cacheRectF, roundRadius, roundRadius, paint)
        paint.xfermode = xfermode
        paint.color = colorStateSelected
        canvas.drawRoundRect(
            innerRectF,
            roundRadius,
            roundRadius,
            paint
        )
        paint.xfermode = null
        canvas.restoreToCount(count)

        paint.color = colorCircle
        canvas.drawCircle(
            currentCircleX,
            circleCenterY,
            sizeCircleRadius * 1f,
            paint
        )
    }

    override fun onClick(v: View?) {
        stateChecked = !stateChecked
        startStateChangedAnim()

    }
}